#include "../include/modules/map.h"
#include "../include/engine/graphics.h"
#include "../lib/GM/include/geometry/shapeGL.h"
#include <stdio.h>
#include <stdlib.h>

#define EPSILON 0.000001

Map* createMap(){
    Map *m = (Map *)malloc(sizeof(Map));
    if(m == NULL){
        fprintf(stderr, "createMap::Erreur de malloc de m\n");
        return NULL;
    }
    m->path = NULL;
    m->texture = NULL;
    m->heightSDL = 0;
    m->widthSDL = 0;
    m->heightGL = 0;
    m->widthGL = 0;
    m->mouseGL.x = 0.0;
    m->mouseGL.y = 0.0;
    m->squareDrew = createSquare(0.0, 0.0, 0.0, 0);
    m->nbNodes = 0;
    m->nodesGL = NULL;
    m->nbSquare = 0;
    m->squareTab = NULL;
    m->wave = 0;
    m->delayMonster = 0;
    m->timerWave = 0;
    m->debug = 0;
    m->pause = 0;

    return m;
}

Map* initMap(Map *m, char *pathMap, GLuint *textureMap, int nbN, CoordOpenGL *nodes, int nbS, Square *squareT, unsigned int width, unsigned int height, float widthGL, float heightGL){
    if(pathMap == NULL || textureMap == NULL || nodes == NULL || squareT == NULL){
        printf("initMap::Un pointeur est NULL\n");
        return NULL;
    }
    m->path = pathMap;
    m->texture = textureMap;
    m->heightSDL = (int)height;
    m->widthSDL = (int)width*3/4;
    m->heightGL = heightGL;
    m->widthGL = widthGL;
    m->mouseGL.x = 10.0;
    m->mouseGL.y = 10.0;
    m->squareDrew = createSquare(10.0, 10.0, 0.0, 0);
    m->nbNodes = nbN;
    m->nodesGL = nodes;
    m->nbSquare = nbS;
    m->squareTab = squareT;
    m->wave = 0;
    m->delayMonster = 35; //Nombre de tours(laps) en ms qui sépare chaque apparition de monstre.
    m->timerWave = m->delayMonster;
    m->debug = 0;
    m->pause = 0;

    return m;
}

void drawMap(GLuint *textureMap){
    if(textureMap == NULL){
        printf("drawMap::textureMap Un pointeur est NULL\n");
        return;
    }
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glColor3ub(255, 255, 255);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, *textureMap);
        glBegin(GL_QUADS);
            //coord
            glTexCoord2f(0, 0);
            glVertex2f(-2, 1.5);
            glTexCoord2f(1, 0);
            glVertex2f(1, 1.5);
            glTexCoord2f(1, 1);
            glVertex2f(1, -1.5);
            glTexCoord2f(0, 1);
            glVertex2f(-2, -1.5);
        glEnd();
    glBindTexture(GL_TEXTURE_2D, 0);
    glDisable(GL_TEXTURE_2D);
}

void drawRoad(CoordOpenGL *nodesGL, Itd itd){
    if(nodesGL == NULL){
        fprintf(stderr, "le tableau de coordonnées n'existe pas\n");
        return;
    }
    int i = 0;
    
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glPushMatrix();
    glColor3ub(itd.chemin.r, itd.chemin.g, itd.chemin.b);
    glBegin(GL_LINE_STRIP);
    for(i=0; i<itd.nbNodes; i++){           
        glVertex2f(nodesGL[i].x , nodesGL[i].y);        
    }
    glEnd();
    glPopMatrix();
}  

void drawNode(CoordOpenGL* nodesGL, Itd itd){
    if(nodesGL == NULL){
        fprintf(stderr, "le tableau de coordonnées n'existe pas\n");
        return;
    }
    glLoadIdentity();
    for(int i=0; i<itd.nbNodes; i++){
        glPushMatrix();
        if(i == 0){
            glColor3ub(itd.in.r, itd.in.g, itd.in.b);
            glTranslatef(nodesGL[i].x, nodesGL[i].y, 0);
        }
        else if(i == (itd.nbNodes -1)){
            glColor3ub(itd.out.r, itd.out.g, itd.out.b);
            glTranslatef(nodesGL[i].x, nodesGL[i].y, 0);
        }
        else{
            glColor3ub(itd.color_node.r, itd.color_node.g, itd.color_node.b);
            glTranslatef(nodesGL[i].x, nodesGL[i].y, 0);
        }
        
        glScalef(0.04, 0.04, 0.);
        drawQuad();
        glPopMatrix();
    }
}

void drawPause(Map *map){
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glPushMatrix();
        glTranslatef(-0.5, 0, 0);
        glScalef(map->heightGL, map->widthGL, 0);
        glPushMatrix();
            glColor4f (1.0, 1.0, 1.0, 0.50);
            drawQuad();
        glPopMatrix();
        glPushMatrix();
            glColor4f (1.0, 1.0, 1.0, 1.0);
            drawOutlineQuad();
        glPopMatrix();
        glPushMatrix();
            glScalef((float)1/8, (float)1/4, 0);
            glPushMatrix();
                glTranslatef(-1, 0, 0);
                glColor4f (0.0, 0.0, 0.0, 0.50);
                drawQuad();
            glPopMatrix();
            glPushMatrix();
                glTranslatef(1, 0, 0);
                glColor4f (0.0, 0.0, 0.0, 0.50);
                drawQuad();
            glPopMatrix();
        glPopMatrix();
    glPopMatrix();
}

void colorMap(SDL_Surface *imgMap, Itd itd){
    if(imgMap == NULL){
        fprintf(stderr, "colorMap:: imgMap n'existe pas\n");
        return;
    }
    int x,y;
    Uint32 pixel;
    Uint8 r,g,b,a;

    SDL_LockSurface(imgMap); /*On bloque la surface*/
    for (y=0; y<imgMap->h; y++){
        for (x=0; x<imgMap->w; x++){
            pixel = getPixel(imgMap,x,y); // On selectionne le pixel situé en (x,y)
            SDL_GetRGBA(pixel, imgMap->format, &r, &g, &b, &a); // On regarde la couleur qu'il a

            if(r == 125 && g == 255 && b == 80){ // On change la couleur des zones constructibles
                r = itd.construct.r;
                g = itd.construct.g;
                b = itd.construct.b;
            }

            pixel=SDL_MapRGBA(imgMap->format, r, g, b, a);// On change la couleur du pixel
            definePixel(imgMap,x,y,pixel); // On réinsère le pixel
        }
    }
    SDL_UnlockSurface(imgMap); /*On libère la surface, elle peut être utilisée*/
}

int sizeConstructMap(SDL_Surface *imgMap){
    int x,y;
    int size = 0;
    Uint32 pixel;
    Uint8 r,g,b,a;

    SDL_LockSurface(imgMap); /*On bloque la surface*/
    for (y=0; y<imgMap->h; y++){
        for (x=0; x<imgMap->w; x++){
            pixel = getPixel(imgMap,x,y); // On selectionne le pixel situé en (x,y)
            SDL_GetRGBA(pixel, imgMap->format, &r, &g, &b, &a); // On regarde la couleur qu'il a

            if(r == 125 && g == 255 && b == 80){ // On change la couleur des zones constructibles
                size++;
            }
        }
    }
    SDL_UnlockSurface(imgMap); /*On libère la surface, elle peut être utilisée*/

    return size;
}

void setConstructMap(SDL_Surface *imgMap, Square *square, int w_height, int w_width, int nbSquare){
    if(imgMap == NULL){
        fprintf(stderr, "imgMap n'existe pas\n");
        return;
    }
    if(square == NULL){
        fprintf(stderr, "le tableau de square n'existe pas\n");
        return;
    }

    int x,y;
    CoordSDL coord;
    CoordOpenGL coordFrag;
    CoordSquare coordtemp;
    int k;
    Uint32 pixel;
    Uint8 r,g,b,a;

    k=0;
    SDL_LockSurface(imgMap); /*On bloque la surface*/
    for (y=0; y<imgMap->h; y++){
        for (x=0; x<imgMap->w; x++){
            pixel = getPixel(imgMap,x,y); // On selectionne le pixel situé en (x,y)
            SDL_GetRGBA(pixel, imgMap->format, &r, &g, &b, &a); // On regarde la couleur qu'il a

            if(r == 125 && g == 255 && b == 80){ // On verifie la couleur des zones constructibles
                coord.x = x;
                coord.y = y;

                coord = changeCoordMark(coord, w_height, w_width, imgMap->w, imgMap->h);    // On change le ratio de l'image en fonction du repere SDL et de la nouvelle taille de map passé en texture
                coordFrag = coordSDLtoCoordOpenGL(coord, w_height, w_width);     //on convertie la coord du pixel selectionné qui deviendra un fragment selectionné
                coordFrag.x +=2.0;
                coordFrag.y +=1.5;
                coordtemp.x = (int)(coordFrag.x/square->lenghtSquare); // nb de carrés dont on s'est deplacé pour etre au point cliqué
                coordtemp.y = (int)(coordFrag.y/square->lenghtSquare);
                // printf("lenghtSquare %f\n", square->lenghtSquare);
                coordFrag.x = coordtemp.x * square->lenghtSquare; //position du carré
                coordFrag.y = coordtemp.y * square->lenghtSquare;
                //printf("%d %d\n", coordSquare.x, coordSquare.y );
                k = 0;
                while(k < nbSquare){
                    // Condition n'est pas égale
                    // (coordFrag.x - ((square[k].coordGL.x)+2.0))>EPSILON || (coordFrag.x - ((square[k].coordGL.x)+2.0))<-EPSILON && (coordFrag.y - ((square[k].coordGL.y)+1.5))>EPSILON || (coordFrag.y - ((square[k].coordGL.y)+1.5))<-EPSILON
                    // Condition est égale
                    // (coordFrag.x - ((square[k].coordGL.x)+2))<EPSILON && (coordFrag.y - ((square[k].coordGL.y)+1.5))<EPSILON
                    // printf("X pix img:%f X tab Square:%f\n",coordSquare.x,square[k].coordGL.x );
                    if((coordFrag.x - ((square[k].coordGL.x)+2))<EPSILON && (coordFrag.y - ((square[k].coordGL.y)+1.5))<EPSILON){
                        square[k].nbFragConstruct++;
                        k = nbSquare;
                    }
                    k++;
                }
            }
        }
    }
    SDL_UnlockSurface(imgMap); /*On libère la surface, elle peut être utilisée*/
}

void changeAvailability(Square squareSelected, Map *map){
    if(map == NULL){
        fprintf(stderr, "changeAvailability::map n'existe pas\n");
        return;
    }
    int i = 0;
    while(i<map->nbSquare){
        if((squareSelected.coordGL.x - (map->squareTab[i].coordGL.x))<EPSILON && (squareSelected.coordGL.y - (map->squareTab[i].coordGL.y))<EPSILON){
            map->squareTab[i].availability = 0;
            break;
        }
        i++;
    }
}